package cn.ilikes.tools.nosql.jpa.clients.indexs.index.lucenes.asytools;

import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.ConcurrentMergeScheduler;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.clients.indexs.ClientIndexingRunTimeException;
import cn.ilikes.tools.nosql.jpa.clients.indexs.index.ABIndexSource;
import cn.ilikes.tools.nosql.jpa.clients.indexs.index.ABLuceneIndexSource;

public class AsyLuceneService {

	private Logger logger = Loggerfactory.instance(AsyLuceneService.class);

	private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

	private AtomicBoolean writes = new AtomicBoolean(false);

	private Queue<Directory> directorys = new ConcurrentLinkedQueue<Directory>();

	private ABIndexSource luceneIndexSource;

	private Analyzer analyzer;

	private ReadLock readlock = lock.readLock();

	private WriteLock writeLock = lock.writeLock();

	private IndexWriter nowIndexWriter;

	private IndexSearcher indexSearcher;

	private IndexReader indexReader;

	private Directory nowDirectory;

	private IndexWriter hdfsIndexWriter;

	public AsyLuceneService(Analyzer analyzer, ABIndexSource luceneIndexSource) {
		super();
		this.analyzer = analyzer;
		this.luceneIndexSource = luceneIndexSource;
	}

	public void init() {
		try {
			Loggerfactory.info(logger, "init Asy Lucene Service  ");
//			ABLuceneIndexSource luceneIndexSource = (ABLuceneIndexSource) this.luceneIndexSource;
//			Directory directory = luceneIndexSource.createDirectory();
//			hdfsIndexWriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_41, this.analyzer));
			createNew();
		} catch (Exception e) {
			throw new ClientIndexingRunTimeException(e);
		}
	}

	private void createNew() {
		try {
			nowDirectory = new RAMDirectory();
			IndexWriter indexWriter = new IndexWriter(nowDirectory, new IndexWriterConfig(Version.LUCENE_41, analyzer));
			
			this.nowIndexWriter = indexWriter;
			writes.set(false);
		} catch (Exception e) {
			throw new ClientIndexingRunTimeException(e);
		}
	}

	public IndexWriter createIndexWriter() {
		try {
			readlock.lock();
			return nowIndexWriter;
		} finally {
			readlock.unlock();
		}
	}

	public void writer() {
		writes.set(true);
	}

	public boolean isWriter() {
		return writes.get();
	}

	public void megDirectory() {
		try {
			Loggerfactory.info(logger, "meg  directory  ");
			writeLock.lock();
			this.nowIndexWriter.commit();
			this.nowIndexWriter.close();
		} catch (Exception e) {
			throw new ClientIndexingRunTimeException(e);
		} finally {
			if (writes.get()) {
				directorys.add(nowDirectory);
			}
			createNew();
			writeLock.unlock();
		}
	}

	public Queue<Directory> getDirectorys() {
		return directorys;
	}

	public IndexSearcher createIndexSearcher() {
		if (indexSearcher == null) {
			synchronized (logger) {
				try {
					ABLuceneIndexSource luceneIndexSource = (ABLuceneIndexSource) this.luceneIndexSource;
					IndexReader reader = createIndexReader();
					if (Loggerfactory.isdebug(logger))
						Loggerfactory.info(logger, "create  " + luceneIndexSource.getIndexConfigs().getName() + "  index searcher " + reader);
					if (reader == null)
						return null;
					IndexSearcher searcher = new IndexSearcher(reader);
					this.indexSearcher = searcher;
				} catch (Exception e) {
					Loggerfactory.error(logger, e.getMessage(), e);
				}
			}
		}
		return indexSearcher;
	}

	public IndexReader createIndexReader() {

		if (indexReader == null) {
			synchronized (logger) {
				try {
					ABLuceneIndexSource luceneIndexSource = (ABLuceneIndexSource) this.luceneIndexSource;
					if (Loggerfactory.isdebug(logger))
						Loggerfactory.info(logger, "create  " + luceneIndexSource.getIndexConfigs().getName() + "  index reader  " + this.indexReader);
					Directory directory = luceneIndexSource.createDirectory();
					//					IndexWriter indexWriter = createIndexWriter();
					//					IndexReader reader = DirectoryReader.open(indexWriter, true);
					IndexReader reader = DirectoryReader.open(directory);
					this.indexReader = reader;
					System.out.println("=========  createIndexReader =========   " + this.indexReader);
				} catch (Exception e) {
					Loggerfactory.error(logger, e.getMessage());
				}
			}
		}
		return indexReader;
	}

	public boolean mreg(Directory directory) {
		IndexWriter hdfsIndexWriter =null;
		try {
			IndexWriterConfig  indexWriterConfig=new IndexWriterConfig(Version.LUCENE_41, this.analyzer);
			
			ABLuceneIndexSource luceneIndexSource = (ABLuceneIndexSource) this.luceneIndexSource;
			Directory directory_ = luceneIndexSource.createDirectory();
			hdfsIndexWriter = new IndexWriter(directory_, indexWriterConfig);
			hdfsIndexWriter.addIndexes(directory);
			return true;
		} catch (Exception e) {
			Loggerfactory.error(logger, e.getMessage());
			return false;
		}finally
		{
			if(hdfsIndexWriter!=null)
				try {
					hdfsIndexWriter.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}

	public void closeHdfsIndexWrite() {
//		try {
//			hdfsIndexWriter.close();
//		} catch (IOException e) {
//			Loggerfactory.error(logger, e);
//		}
	}
}
